{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.7.3\n",
      "IPython 7.6.1\n",
      "\n",
      "tensorflow 1.13.1\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p tensorflow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Convolutional General Adversarial Networks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implementation of General Adversarial Nets (GAN) where both the discriminator and generator have convolutional and deconvolutional layers, respectively. In this example, the GAN generator was trained to generate MNIST images.\n",
    "\n",
    "Uses\n",
    "\n",
    "- samples from a random normal distribution (range [-1, 1])\n",
    "- dropout\n",
    "- leaky relus\n",
    "- batch normalization\n",
    "- separate batches for \"fake\" and \"real\" images (where the labels are 1 = real images, 0 = fake images)\n",
    "- MNIST images normalized to [-1, 1] range\n",
    "- generator with tanh output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/device:GPU:0'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "import pickle as pkl\n",
    "\n",
    "tf.test.gpu_device_name()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:17: read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:260: maybe_download (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please write your own downloading logic.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:262: extract_images (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting MNIST_data/train-images-idx3-ubyte.gz\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:267: extract_labels (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n",
      "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:64: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.dense instead.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n",
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:65: batch_normalization (from tensorflow.python.layers.normalization) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.batch_normalization instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:74: conv2d_transpose (from tensorflow.python.layers.convolutional) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.conv2d_transpose instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:77: dropout (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.dropout instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-c57ae97e26b0>:121: conv2d (from tensorflow.python.layers.convolutional) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.conv2d instead.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.cast instead.\n"
     ]
    }
   ],
   "source": [
    "### Abbreviatiuons\n",
    "# dis_*: discriminator network\n",
    "# gen_*: generator network\n",
    "\n",
    "########################\n",
    "### Helper functions\n",
    "########################\n",
    "\n",
    "def leaky_relu(x, alpha=0.0001):\n",
    "    return tf.maximum(alpha * x, x)\n",
    "\n",
    "\n",
    "########################\n",
    "### DATASET\n",
    "########################\n",
    "\n",
    "mnist = input_data.read_data_sets('MNIST_data')\n",
    "\n",
    "\n",
    "#########################\n",
    "### SETTINGS\n",
    "#########################\n",
    "\n",
    "# Hyperparameters\n",
    "learning_rate = 0.001\n",
    "training_epochs = 50\n",
    "batch_size = 64\n",
    "dropout_rate = 0.5\n",
    "\n",
    "# Architecture\n",
    "dis_input_size = 784\n",
    "gen_input_size = 100\n",
    "\n",
    "# Other settings\n",
    "print_interval = 200\n",
    "\n",
    "#########################\n",
    "### GRAPH DEFINITION\n",
    "#########################\n",
    "\n",
    "g = tf.Graph()\n",
    "with g.as_default():\n",
    "    \n",
    "    # Placeholders for settings\n",
    "    dropout = tf.placeholder(tf.float32, shape=None, name='dropout')\n",
    "    is_training = tf.placeholder(tf.bool, shape=None, name='is_training')\n",
    "    \n",
    "    # Input data\n",
    "    dis_x = tf.placeholder(tf.float32, shape=[None, dis_input_size],\n",
    "                           name='discriminator_inputs')     \n",
    "    gen_x = tf.placeholder(tf.float32, [None, gen_input_size],\n",
    "                           name='generator_inputs')\n",
    "\n",
    "\n",
    "    ##################\n",
    "    # Generator Model\n",
    "    ##################\n",
    "\n",
    "    with tf.variable_scope('generator'):\n",
    "        \n",
    "        # 100 => 784 => 7x7x64\n",
    "        gen_fc = tf.layers.dense(inputs=gen_x, units=3136,\n",
    "                                 bias_initializer=None, # no bias required when using batch_norm\n",
    "                                 activation=None)\n",
    "        gen_fc = tf.layers.batch_normalization(gen_fc, training=is_training)\n",
    "        gen_fc = leaky_relu(gen_fc)\n",
    "        gen_fc = tf.reshape(gen_fc, (-1, 7, 7, 64))\n",
    "        \n",
    "        # 7x7x64 => 14x14x32\n",
    "        deconv1 = tf.layers.conv2d_transpose(gen_fc, filters=32, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv1 = tf.layers.batch_normalization(deconv1, training=is_training)\n",
    "        deconv1 = leaky_relu(deconv1)     \n",
    "        deconv1 = tf.layers.dropout(deconv1, rate=dropout_rate)\n",
    "        \n",
    "        # 14x14x32 => 28x28x16\n",
    "        deconv2 = tf.layers.conv2d_transpose(deconv1, filters=16, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv2 = tf.layers.batch_normalization(deconv2, training=is_training)\n",
    "        deconv2 = leaky_relu(deconv2)     \n",
    "        deconv2 = tf.layers.dropout(deconv2, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x16 => 28x28x8\n",
    "        deconv3 = tf.layers.conv2d_transpose(deconv2, filters=8, \n",
    "                                             kernel_size=(3, 3), strides=(1, 1), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv3 = tf.layers.batch_normalization(deconv3, training=is_training)\n",
    "        deconv3 = leaky_relu(deconv3)     \n",
    "        deconv3 = tf.layers.dropout(deconv3, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x8 => 28x28x1\n",
    "        gen_logits = tf.layers.conv2d_transpose(deconv3, filters=1, \n",
    "                                                kernel_size=(3, 3), strides=(1, 1), \n",
    "                                                padding='same',\n",
    "                                                bias_initializer=None,\n",
    "                                                activation=None)\n",
    "        gen_out = tf.tanh(gen_logits, 'generator_outputs')\n",
    "\n",
    "\n",
    "    ######################\n",
    "    # Discriminator Model\n",
    "    ######################\n",
    "    \n",
    "    def build_discriminator_graph(input_x, reuse=None):\n",
    "\n",
    "        with tf.variable_scope('discriminator', reuse=reuse):\n",
    "            \n",
    "            # 28x28x1 => 14x14x8\n",
    "            conv_input = tf.reshape(input_x, (-1, 28, 28, 1))\n",
    "            conv1 = tf.layers.conv2d(conv_input, filters=8, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv1 = tf.layers.batch_normalization(conv1, training=is_training)\n",
    "            conv1 = leaky_relu(conv1)\n",
    "            conv1 = tf.layers.dropout(conv1, rate=dropout_rate)\n",
    "            \n",
    "            # 14x14x8 => 7x7x32\n",
    "            conv2 = tf.layers.conv2d(conv1, filters=32, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv2 = tf.layers.batch_normalization(conv2, training=is_training)\n",
    "            conv2 = leaky_relu(conv2)\n",
    "            conv2 = tf.layers.dropout(conv2, rate=dropout_rate)\n",
    "\n",
    "            # fully connected layer\n",
    "            fc_input = tf.reshape(conv2, (-1, 7*7*32))\n",
    "            logits = tf.layers.dense(inputs=fc_input, units=1, activation=None)\n",
    "            out = tf.sigmoid(logits)\n",
    "            \n",
    "        return logits, out    \n",
    "\n",
    "    # Create a discriminator for real data and a discriminator for fake data\n",
    "    dis_real_logits, dis_real_out = build_discriminator_graph(dis_x, reuse=False)\n",
    "    dis_fake_logits, dis_fake_out = build_discriminator_graph(gen_out, reuse=True)\n",
    "\n",
    "\n",
    "    #####################################\n",
    "    # Generator and Discriminator Losses\n",
    "    #####################################\n",
    "    \n",
    "    # Two discriminator cost components: loss on real data + loss on fake data\n",
    "    # Real data has class label 1, fake data has class label 0\n",
    "    dis_real_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_real_logits, \n",
    "                                                            labels=tf.ones_like(dis_real_logits))\n",
    "    dis_fake_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits, \n",
    "                                                            labels=tf.zeros_like(dis_fake_logits))\n",
    "    dis_cost = tf.add(tf.reduce_mean(dis_fake_loss), \n",
    "                      tf.reduce_mean(dis_real_loss), \n",
    "                      name='discriminator_cost')\n",
    " \n",
    "    # Generator cost: difference between dis. prediction and label \"1\" for real images\n",
    "    gen_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits,\n",
    "                                                       labels=tf.ones_like(dis_fake_logits))\n",
    "    gen_cost = tf.reduce_mean(gen_loss, name='generator_cost')\n",
    "    \n",
    "    \n",
    "    #########################################\n",
    "    # Generator and Discriminator Optimizers\n",
    "    #########################################\n",
    "      \n",
    "    dis_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    dis_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='discriminator')\n",
    "    dis_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='discriminator')\n",
    "    \n",
    "    with tf.control_dependencies(dis_update_ops): # required to upd. batch_norm params\n",
    "        dis_train = dis_optimizer.minimize(dis_cost, var_list=dis_train_vars,\n",
    "                                           name='train_discriminator')\n",
    "    \n",
    "    gen_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    gen_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator')\n",
    "    gen_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='generator')\n",
    "    \n",
    "    with tf.control_dependencies(gen_update_ops): # required to upd. batch_norm params\n",
    "        gen_train = gen_optimizer.minimize(gen_cost, var_list=gen_train_vars,\n",
    "                                           name='train_generator')\n",
    "    \n",
    "    # Saver to save session for reuse\n",
    "    saver = tf.train.Saver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minibatch: 0001 | Dis/Gen Cost:    1.630/0.866\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.850/1.879\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.606/2.467\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.695/1.661\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.149/1.297\n",
      "Epoch:     0001 | Dis/Gen AvgCost: 0.820/1.887\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.707/1.486\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.924/1.438\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.751/1.508\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.899/1.611\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.914/1.535\n",
      "Epoch:     0002 | Dis/Gen AvgCost: 0.954/1.510\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.498/1.955\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.757/1.670\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.100/1.204\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.656/2.054\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.036/1.174\n",
      "Epoch:     0003 | Dis/Gen AvgCost: 0.784/1.720\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.576/0.992\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.663/2.002\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.869/1.773\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.675/1.772\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.881/1.489\n",
      "Epoch:     0004 | Dis/Gen AvgCost: 0.898/1.575\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.201/1.386\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.245/1.606\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.281/1.015\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.925/1.124\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.126/1.634\n",
      "Epoch:     0005 | Dis/Gen AvgCost: 1.037/1.435\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.853/1.626\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.204/0.929\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.070/1.365\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.366/0.927\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.253/1.500\n",
      "Epoch:     0006 | Dis/Gen AvgCost: 1.168/1.186\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.590/0.945\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.822/1.563\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.894/1.410\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.292/1.131\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.361/1.005\n",
      "Epoch:     0007 | Dis/Gen AvgCost: 1.248/1.103\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.860/0.697\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.291/0.986\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.097/0.934\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.316/0.788\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.437/0.885\n",
      "Epoch:     0008 | Dis/Gen AvgCost: 1.298/0.995\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.150/1.072\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.177/1.148\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.351/0.884\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.434/0.797\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.291/0.929\n",
      "Epoch:     0009 | Dis/Gen AvgCost: 1.333/0.968\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.324/0.764\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.255/0.942\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.181/1.007\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.132/1.134\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.170/1.249\n",
      "Epoch:     0010 | Dis/Gen AvgCost: 1.328/0.922\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.539/0.739\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.181/1.186\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.014/1.331\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.380/0.884\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.441/0.893\n",
      "Epoch:     0011 | Dis/Gen AvgCost: 1.306/0.949\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.248/0.953\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.421/0.751\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.323/0.891\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.363/0.912\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.174/1.112\n",
      "Epoch:     0012 | Dis/Gen AvgCost: 1.334/0.931\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.463/0.792\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.296/0.992\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.213/1.037\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.273/0.899\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.282/0.893\n",
      "Epoch:     0013 | Dis/Gen AvgCost: 1.323/0.910\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.192/0.921\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.287/0.933\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.292/0.898\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.164/0.945\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.469/0.776\n",
      "Epoch:     0014 | Dis/Gen AvgCost: 1.312/0.890\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.363/0.876\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.398/0.759\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.099/1.088\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.415/0.831\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.287/0.813\n",
      "Epoch:     0015 | Dis/Gen AvgCost: 1.310/0.896\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.309/0.910\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.397/0.829\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.221/0.949\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.284/0.918\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.315/0.737\n",
      "Epoch:     0016 | Dis/Gen AvgCost: 1.306/0.860\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.193/0.901\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.339/0.908\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.119/0.969\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.293/0.907\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.368/0.882\n",
      "Epoch:     0017 | Dis/Gen AvgCost: 1.320/0.892\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.308/1.014\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.194/0.936\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.536/0.755\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.443/0.810\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.288/0.730\n",
      "Epoch:     0018 | Dis/Gen AvgCost: 1.315/0.867\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.259/0.979\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.307/0.822\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.242/0.845\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.422/0.891\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.263/0.904\n",
      "Epoch:     0019 | Dis/Gen AvgCost: 1.306/0.866\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.204/0.811\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.340/0.810\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.278/0.963\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.249/0.936\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.285/0.945\n",
      "Epoch:     0020 | Dis/Gen AvgCost: 1.316/0.853\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.370/0.772\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.478/0.762\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.440/0.822\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.269/0.809\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.260/0.923\n",
      "Epoch:     0021 | Dis/Gen AvgCost: 1.324/0.837\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.401/0.892\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.361/0.762\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.121/1.012\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.366/0.822\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.484/0.744\n",
      "Epoch:     0022 | Dis/Gen AvgCost: 1.314/0.851\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.207/0.829\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.320/0.786\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.327/0.807\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.250/0.909\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.339/0.769\n",
      "Epoch:     0023 | Dis/Gen AvgCost: 1.323/0.833\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.363/0.825\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.416/0.738\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.290/0.876\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.257/0.825\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.510/0.633\n",
      "Epoch:     0024 | Dis/Gen AvgCost: 1.323/0.841\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.291/0.694\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.400/0.720\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.340/0.802\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.339/0.784\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.211/0.886\n",
      "Epoch:     0025 | Dis/Gen AvgCost: 1.339/0.811\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.395/0.865\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.400/0.823\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.357/0.811\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.404/0.741\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.298/0.930\n",
      "Epoch:     0026 | Dis/Gen AvgCost: 1.340/0.819\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.257/0.833\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.359/0.772\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.453/0.798\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.389/0.853\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.447/0.754\n",
      "Epoch:     0027 | Dis/Gen AvgCost: 1.340/0.808\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.353/0.764\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.353/0.811\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.458/0.748\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.448/0.753\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.475/0.696\n",
      "Epoch:     0028 | Dis/Gen AvgCost: 1.349/0.792\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.271/0.932\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.294/0.894\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.156/0.866\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.292/0.778\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.309/0.817\n",
      "Epoch:     0029 | Dis/Gen AvgCost: 1.347/0.799\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.459/0.727\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.396/0.753\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.367/0.754\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.336/0.785\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.304/0.756\n",
      "Epoch:     0030 | Dis/Gen AvgCost: 1.347/0.780\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.431/0.726\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.348/0.793\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.102/0.823\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.276/0.772\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.390/0.776\n",
      "Epoch:     0031 | Dis/Gen AvgCost: 1.337/0.801\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.507/0.704\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.295/0.873\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.312/0.835\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.346/0.842\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.328/0.721\n",
      "Epoch:     0032 | Dis/Gen AvgCost: 1.342/0.792\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.401/0.717\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.436/0.737\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.332/0.774\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.311/0.804\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.391/0.650\n",
      "Epoch:     0033 | Dis/Gen AvgCost: 1.352/0.783\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.317/0.740\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.343/0.810\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.394/0.717\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.455/0.779\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.445/0.704\n",
      "Epoch:     0034 | Dis/Gen AvgCost: 1.348/0.785\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.294/0.791\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.277/0.886\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.349/0.721\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.297/0.717\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.320/0.777\n",
      "Epoch:     0035 | Dis/Gen AvgCost: 1.353/0.780\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.338/0.756\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.273/0.778\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.325/0.865\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.438/0.717\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.328/0.785\n",
      "Epoch:     0036 | Dis/Gen AvgCost: 1.352/0.770\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.375/0.764\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.453/0.723\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.270/0.807\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.392/0.775\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.318/0.824\n",
      "Epoch:     0037 | Dis/Gen AvgCost: 1.353/0.773\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.270/0.874\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.214/0.833\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.456/0.666\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.400/0.824\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.328/0.736\n",
      "Epoch:     0038 | Dis/Gen AvgCost: 1.354/0.776\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.332/0.743\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.389/0.710\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.375/0.708\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.296/0.758\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.337/0.783\n",
      "Epoch:     0039 | Dis/Gen AvgCost: 1.356/0.765\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.388/0.706\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.371/0.712\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.349/0.698\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.380/0.723\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.371/0.746\n",
      "Epoch:     0040 | Dis/Gen AvgCost: 1.358/0.759\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.349/0.702\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.315/0.742\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.353/0.760\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.335/0.799\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.403/0.726\n",
      "Epoch:     0041 | Dis/Gen AvgCost: 1.362/0.755\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.363/0.782\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.335/0.742\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.344/0.751\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.338/0.740\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.460/0.735\n",
      "Epoch:     0042 | Dis/Gen AvgCost: 1.361/0.764\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.308/0.767\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.367/0.764\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.382/0.764\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.419/0.625\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.393/0.777\n",
      "Epoch:     0043 | Dis/Gen AvgCost: 1.361/0.753\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.413/0.749\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.370/0.724\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.314/0.756\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.321/0.763\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.354/0.771\n",
      "Epoch:     0044 | Dis/Gen AvgCost: 1.364/0.752\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.363/0.748\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.365/0.727\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.439/0.714\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.429/0.696\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.427/0.699\n",
      "Epoch:     0045 | Dis/Gen AvgCost: 1.363/0.745\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.398/0.713\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.408/0.717\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.298/0.734\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.345/0.805\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.331/0.828\n",
      "Epoch:     0046 | Dis/Gen AvgCost: 1.366/0.752\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.319/0.751\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.482/0.713\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.341/0.803\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.386/0.651\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.428/0.701\n",
      "Epoch:     0047 | Dis/Gen AvgCost: 1.369/0.758\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.378/0.747\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.355/0.716\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.357/0.686\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.333/0.767\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.380/0.712\n",
      "Epoch:     0048 | Dis/Gen AvgCost: 1.370/0.735\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.409/0.706\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.307/0.789\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.396/0.731\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.375/0.711\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.365/0.782\n",
      "Epoch:     0049 | Dis/Gen AvgCost: 1.371/0.733\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.409/0.701\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.369/0.728\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.315/0.730\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.321/0.774\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.336/0.735\n",
      "Epoch:     0050 | Dis/Gen AvgCost: 1.372/0.735\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### TRAINING & EVALUATION\n",
    "##########################\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    \n",
    "    avg_costs = {'discriminator': [], 'generator': []}\n",
    "\n",
    "    for epoch in range(training_epochs):\n",
    "        dis_avg_cost, gen_avg_cost = 0., 0.\n",
    "        total_batch = mnist.train.num_examples // batch_size\n",
    "\n",
    "        for i in range(total_batch):\n",
    "            \n",
    "            batch_x, batch_y = mnist.train.next_batch(batch_size)\n",
    "            batch_x = batch_x*2 - 1 # normalize\n",
    "            batch_randsample = np.random.uniform(-1, 1, size=(batch_size, gen_input_size))\n",
    "            \n",
    "            # Train\n",
    "            \n",
    "            _, dc = sess.run(['train_discriminator', 'discriminator_cost:0'],\n",
    "                             feed_dict={'discriminator_inputs:0': batch_x, \n",
    "                                        'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            _, gc = sess.run(['train_generator', 'generator_cost:0'],\n",
    "                             feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            dis_avg_cost += dc\n",
    "            gen_avg_cost += gc\n",
    "\n",
    "            if not i % print_interval:\n",
    "                print(\"Minibatch: %04d | Dis/Gen Cost:    %.3f/%.3f\" % (i + 1, dc, gc))\n",
    "                \n",
    "\n",
    "        print(\"Epoch:     %04d | Dis/Gen AvgCost: %.3f/%.3f\" % \n",
    "              (epoch + 1, dis_avg_cost / total_batch, gen_avg_cost / total_batch))\n",
    "        \n",
    "        avg_costs['discriminator'].append(dis_avg_cost / total_batch)\n",
    "        avg_costs['generator'].append(gen_avg_cost / total_batch)\n",
    "    \n",
    "    \n",
    "    saver.save(sess, save_path='./gan-conv.ckpt')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(range(len(avg_costs['discriminator'])), \n",
    "         avg_costs['discriminator'], label='discriminator')\n",
    "plt.plot(range(len(avg_costs['generator'])),\n",
    "         avg_costs['generator'], label='generator')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/training/saver.py:1266: checkpoint_exists (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use standard file APIs to check for files with this prefix.\n",
      "INFO:tensorflow:Restoring parameters from ./gan-conv.ckpt\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAd4AAAHUCAYAAACUBUmlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOzdeaCV0/oH8O8SEWXIqTQXijLGoZAhY4bUjQyXRKkbMl2XuqbMMl8z59KvjIlEkiFdJEM6UVFpkCZSUpSM8f7+6DzPed7Ou8/eZw/r7OH7+aentae137PPfs963met5YIgABEREfmxSXV3gIiIqJDwxEtEROQRT7xEREQe8cRLRETkEU+8REREHvHES0RE5FFKJ17nXGfn3Bzn3Hzn3KB0dYqIiChfuWTn8TrnagCYC+AoAEsBTAFwehAEs9LXPSIiovyyaQqP3R/A/CAIFgCAc24EgK4AYp54i4qKghYtWqTwkoVj6tSpK4MgqJfKc/B4Jy4dxxvgMa8Kfsb94vH2q7LjncqJtzGAJeb/SwG03/hOzrl+APoBQLNmzVBaWprCSxYO59yiJB/H452EZI932WN5zJPAz7hfPN5+VXa8U7nG6yLaKuStgyAoCYKgOAiC4nr1Uh5QUBw83v7xmPvF4+0Xj3f6pXLiXQqgqfl/EwDfpNYdIiKi/JbKiXcKgFbOuZbOuZoATgMwJj3dIiIiyk9JX+MNgmC9c24AgDcA1AAwNAiCmWnrWQH6888/q7sLRESUYakUVyEIgnEAxqWpL0RERHmPK1cRERF5lNKINx/YBUSciyrU9qdGjRrV+vpERJR5HPESERF5xBMvERGRRwWbam7Xrh0AYNas8hUuL7/8co1vuukm731avXq199ckog1kVsGzzz6rbVdccYXGhxxyCABgxIgRfjtGeYcjXiIiIo8KdsS7YMECAMDvv/+ubdU9j3a77bar1tfPFuvXrwcAnH322dr2zDPPaFynTh0AwKJF5Uuhbrvttn46l6ekyFCOPQBsttlm1dUdbwYOHKjxfffdBwD49ddfI+/7/PPPAwBGjRqlbUVFRRpfddVVAICmTcsX9OvUqZPGP//8s8Z//fUXAKBRo0ZJ970QrVu3TuPRo0cDAC6++GJtW7Vqlcb28yvfGcXFxdr26quvarzppn5PhRzxEhERecQTLxERkUcFlWq2aeU999wTADBp0iRte+mllzS+9dZb/XWMMHXqVI379u0LAPj0008j77t27VoAwH//+19ts4VxheKPP/4AAAwbNkzbXnnlFY1r164NABg+fLi22bnidt56hw4dAAAzZszQtlNPPVVj+xq5TtK8QHl6GSj/frBpxy222EJjSXPadPy3336r8YUXXljhtexz7bvvvhrLnraSAgWA1q1ba/zRRx8BCP+8Hn/8cY1r1apVoS+2r/nqiSee0FhSzPYY7bzzzhr36NFD47vuugsA8Oabb2rbgAEDNH7kkUfS39lKcMRLRETkEU+8REREHhVUqnnx4sUa2xSRaNiwoc/uFCSb5rNpzY4dO2ocVVW6ySblfyNK1ei5556biS5mtZ9++knjO+64AwBwww03aJtNH5eWlgIIL4tqj6O14447AgA+/vhjbXvuuec0vv/++wGEU6O5yh6D/fbbT+M1a9YACKcd7fE++uijAYSPsT22wt5uU8GTJ0+OjBM1fvz4Cs/72WefaZukr/PZo48+qrFcarn77ru17W9/+5vGdpaIHKexY8dq2y+//JKxfsbDES8REZFHBTXitX+ty+jX/nVav359730qFDLStfNx+/Xrp3HUKPfggw/WWEZ3ANC+fftMdDFryV/2QLjIyY50RefOnTXeZ599Kn1eO6/UFvYIKeAB8qtwx450bAGffCfEmk8vq9ktX75c22yxjxxP+/NKVazRddeuXQH4n39a3WwGQT6z9nPeuHFjjefOnavxW2+9VeG5zjrrrEx0MSEc8RIREXnEEy8REZFHBZWnsPPg7JxeweKq9LJpoZKSEgDh5d3s7ZZsYPHyyy9rWyEupympxW+++Ubb/vWvf1W431ZbbaWxXeA/nh9//FHjkSNHVrjdpq3zaflImza3lzhOP/10AMDrr78e+bgrr7yyQtugQYM0lrUBbEGWXYbWpu6lwMv2pUuXLhrLUpT2coxdirJQ9+7+/PPPNZbP7IEHHhh5X3t5Sn7O8jMCgD322CMTXUxI3BGvc26oc26Fc+5z01bXOTfeOTev7N/C+1YkIiJKQiKp5mEAOm/UNgjAhCAIWgGYUPZ/IiIiiiNuqjkIgonOuRYbNXcFcFhZPBzAOwAGIsvNnj270tvtbhV2bpitLKTK2aplOydUjm2s9HK9evU0luXyatasmYku5gxJNdu9oX/77bcK97PL5G2zzTaVPqfdvcWm4r744osK97VzJvNJrN/n999/H0B4rnmsec9i66231njcuHEAypffBMIp+gceeEBjSXnutddeiXabNnLKKacAAL7++mtts0sA2xkAktKX7xYgnPr3LdniqgZBECwDgLJ/Y87Dcc71c86VOudKv/vuuyRfjhLF4+0fj7lfPN5+8XinX8aLq4IgKAFQAgDFxcUVl3nx6Mgjj9RYVuWxc+7sylYTJ07U+IADDgCQGyMwn8fbFqacf/75AMr3yASAH374odLH2z10ZZUlIDeOs5WpYy6jU1sUaMnx++CDD+L1T2OZ/wmERwdCRhFAeuejplM6j/fMmTM1Pu+88wAAZ555prZ169ZN45122gkA8MILL2ib/R2QdjtithkK2fwDqN5Vk6oqm77Do9hsTf/+/TW22bXBgwcDqN5RrpXsiHe5c64hAJT9uyJ9XSIiIspfyZ54xwDoVRb3AvByJfclIiKiMnFTzc65Z7GhkKrIObcUwGAAQwCMdM71AbAYQI/Yz5A97LxEmfto06E2LWQX25aF1P/zn/9oW5s2bTLWz1xhCxVk7mO89LJd4u7ee+/VuFmzZmnuXe7bfPPNAQBbbrmltsmesADQsmVLALGXc5RUW58+fbQtKr1s2WKfunXrVrHHucculTlhwgQA4X2e7Z7EUpQVtTFCVe2www4AgGXLlmlbvEIuCps3bx6A8OUT+/ux//77axw1/706JVLVfHqMm45Ic1+IiIjyHv/EIiIi8ijvl4y0aaEpU6ZobJd1i2JTprKzRdu2bbXNVuROnz4dQHhJt0KY+2v3ArUpsyiyM5St7DzmmGMy07E8IburxKqAPfTQQwEAa9eu1TY7j/fCCy8EEN5BJxZJV9u0dKGyn1E7L/2dd96p9HEyF92m/u3vhb2UtWLFhnpUu4eunVVB8c2aNQtAOL1s2dkA2ba7Fke8REREHuX9iHfNmjUan3POORpL4YksRg6UFzxs3D5jxgwAwOrVq7XNjoilyGX48OHaZucC5qtp06YlfF/5a3/vvffWtu233z7tfconUsBnC9Ls5h6yAL8d5dpF+auSdZHntZssXHLJJVXscf753//+p7FkDuwqa8cee6zGMvKqXbu2ttlitk6dOmks3z/xihEpzM7Nve666yrcbj/zu+yyi48uJYUjXiIiIo944iUiIvIo71PNNh36/fffV7hdljoEgLPPPltjm1aWIiCb8rPL6ckScdmc2sgESbEnQlJEo0aN0jY7F7q4uDh9HcsTkp7fd999te3DDz/UWNLDtoDH7rH7/PPPJ/xa8hm2c6uZag6nLnv16lXJPcMpZmGXpLTzseUSmN1kwRZfyRxuCvv22281tpsjCPsdnM17SHPES0RE5BFPvERERB7lfap5n3320dimIST1adNpdm7ue++9p7Gk9GLtJSuVurK0ZKGwVeJDhgwBEHtOnaQyx4wZo21vvvmmxpdffrnGMo+ySZMm6etsDtpuu+0AAA899JC2yU5ZAFBSUgIgXIlslx2Uilk7h9HONW/cuLHGshvXwoULta1nz54aP/nkk8m9iQJnl5yU3Y8su6wh08vx2Ut89nKgyJVjyBEvERGRRzzxEhEReZS3qWZJD7dv317bli9frrGkjV966SVtO/DAAzW+9tprNbaLcAhb4WzT0oXEpualwvnzzz+v9L72WNqlEG+44QaNJYXar18/bbviiis0lp2lCsVuu+2msT0Ot912G4DozydQvkynXZbQVpXXrFlT4+OPPx5AuAp3xIgRGsslGVthTdHksgoQXuQhalejBx980EeX8oZdICbq0l+uLHnKES8REZFHeTvilU0Q7MjULq0n8x3twudffPGFxosWLar0+Xv37q1x1Py9QmALeezoKcqvv/4KIFwc9PHHH2tsiyZkrp4dBd91110ajx49GgBw1FFHJdPtnGPnI9pMjBw/2cQDCI8Idt11VwDA5MmTtS3WMpKHHHIIgPCI144obr/9dgDAc889V/U3UGDs3q/33Xdf5H1kSdqGDRt66VO+sMv6ShbNLrvZqlUr731KBke8REREHvHES0RE5FHepprr1q0LABg5cqS22WKR+++/HwAwe/ZsbXvqqacqfU5bpGLTSYVq7NixGtu9eaPIXFKbqvz00081tnNV5Wdil4Sz84NPPPFEAOElQO1yfFFsYYvsX2uX68sVNlUsc2vtDjl2z+ihQ4dWeEws//jHPwAAjz32mLbZ9P+SJUuS7HHhWLVqFQDgnnvuibzdzqe++eabvfQp39hjuOeeewIon4MOAI0aNfLep2TEHfE655o65952zs12zs10zl1c1l7XOTfeOTev7N/tMt9dIiKi3JZIqnk9gMuCIGgDoAOAC5xzbQEMAjAhCIJWACaU/Z+IiIgqETfVHATBMgDLyuK1zrnZABoD6ArgsLK7DQfwDoCBGellCqSyEwCuvvpqjd99910AwKxZs7StRo0aGtu5eGLgwPK3lyvVc5lUlYrMV199FUB4mUIbyzxSoHwO9u67765tX375pcZSIW3nlNpLBvHkYopZ2EpyqYydMmVKys/bunVrAOGUvd3pKGpnLwrvKGTXAYgydepUje0lAUqcnaViP5/iqquu0viVV17x0qdkVKm4yjnXAkA7AJMBNCg7KcvJuX6Mx/RzzpU650q/++671HpLcfF4+8dj7hePt1883umXcHGVc642gFEALgmCYE0iBRsAEARBCYASACguLq64dItH9q8lWfXHrmwVi4yQcmHPWJ/H2xYy2EIcYeef2sX5o9g51GeccQaA2PuTSqGUzVDIKBmInlOc6Oc1Gdn0GU+W/Py23357bbMjikQXn7dzKhcsWKCx3awkVdV9vO3nctCg8itsc+bMqXDfRx99VONcHeVW9/GOReb2H3nkkdpmN15Jp08++QRAeP/2u+++W+N42Y6NJTTidc5thg0n3aeDIHixrHm5c65h2e0NAayo0isTEREVoESqmh2AxwHMDoLgbnPTGAC9yuJeAF5Of/eIiIjySyKp5oMA9ATwmXNuWlnblQCGABjpnOsDYDGAHpnpYmbInFy74P7PP/+ssZ33KYvQx1qMvlA1aNCg0ttt+lmOt91YwaYlo4rZatWqpbEttJL52PXrl5cVxFuykion8yOPOeYYbbNp0nnz5gEIF7G1adNG4+effx4A0L9/f2077rjjNM6l/Xztspsvv1w+nli6dCmA8PfAI488UuHx9juluhfttxuR5Bs791/YS04zZszQWOb8JksKSe08d/udVFWJVDVPAhDrAtkRSb8yERFRAeKSkURERB7l7ZKR8dSrVw9AeJnI7t27V/oYW6VL4VTwBRdcACCc/rHpekkly7J6G7MV51I9fuutt2qbrQi1KWZKD0nV2910bFpN5k7b6mS7fJ/8TOzSnh07dsxMZzNEPq82vXz22WdrLEuNxnPuuedqnMlq+kTYn1G+karmF198MfJ2+3OUz6XdHa0qJNWcrt2kOOIlIiLyqGBHvPKXaLdu3bRt5cqVGsuqQPa+TZo08dS73GBXUXrggQdC/25MNjywBVn28Tam6mMzD3//+981lj2Q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j82bY+4TP+N+8Xj7VdnxTuUab9Q3YYW8dRAEJUEQFAdBUFyvXsoDCoqDx9s/HnO/eLz94vFOv1RGvEsBNDX/bwLgm9S6Q1Qu06NcIsotn3/+ucZr1qwBABx44IHV1Z2kpTLinQKglXOupXOuJoDTAIxJT7eIiIjyU9Ij3iAI1jvnBgB4A0ANAEODIJiZtp4RVcHatWs1rlOnTjX2hIjSYf369QCAffbZR9tmziw/xWyyyYZxY/v25aVFkyZN8tS71KSSakYQBOMAjEtTX4iIiPIeV64iIiLyKKURL5Evf/31l8bNmjUDAHz99dfa1qBBA42//fZbfx0jooy48847AYR/z+33gMTr1q1L+Dnt4yVVXR044iUiIvKIJ14iIiKPmGpO0p9//lmhrUaNGik9F+etbvDFF18AAHr37q1tdrWcP/74o8Jjfv3118x3jIgyyq5Wd9tttwEAfvjhh8j7ytKVU6ZMifu8F154IQDgoYce0rbNNttMY9/fHxzxEhEReZRXI16Z9wWUF9tceuml2nb11Vcn/Fz2L6/FixcDADp37qxtS5aUL1MtI933339f23bfffcKz2nnmm611VYV+r355psn3L988Pvvv2ts/xIdNGjDDpO//fZbws/VoUOH9HWMKAXLly/X+OKLL9bYZrS+/PJLAMCsWeV7yhxwwAEa33XXXQCAoqIibWvUqFH6O5tlVq1apXHUSNcWREkWbNNNo09jffr00fipp54CEC6uspkz+a7x9R3MES8REZFHPPESERF5lFepZinKAcrTFNdcc422zZ07V+OhQ4cCCBdJ2TTHOeeco7EsU7Z06dLI15X0x/77769tdhcPKQLYfvvttc2mom+44YaY7ynf2HT75ZdfrvHLL7+ssU1BV8amna699to09C67SPrLfm7/+9//ajxs2DAAwC233KJtAwYM8NM5AhBOFR977LEAwpeh7CUr+3m1KU/x1ltvabz33nsDAJo0aaJtN954o8a9evVKpdtZ6+9//3ult8scfqD8+9QeY7u85OzZszWO+k6xz+X7Mh9HvERERB7xxEtERORRXqWaW7ZsqbGkERYtWqRtL7zwgsavvfYagHBlm02DRqWCYpFUh50LZtPWsm/kKaecom3XXXddws+fD1566SUAwD//+U9tW7hwoca24tOmjirTvXt3jXNxT84o48aV7zly/PHHV7jdzj2Uz67MUQTKq2EBYMSIEQDC6Tf7ed9yyy3T0OPCsXr1agBAly5dtM3OL49XhR+1XKH9rEfFNm0t31kAcOaZZwJIfu2AbGW/r6O0adNG46lTpwII/85Mnz5d46jvkW222UZje2nSN454iYiIPMqrEa+dGyt/+cicUAB47LHHNF65cmWFx8dbOapmzZoa29FCSUkJgPL5vgBw0UUXaWxHKYXk888/11gKqb766qvI+5566qkaf/TRRwDCI+IottAol9nCjzPOOKPC7bYoJ142wB4zmdtsP9c77bSTxra4TVYJizUnspDYrMDo0aM1PuusswDEH9nG+p44/PDDNZZ1Buzc3A8++EBjWY3Jfk+NGjVK43vvvTf0PPki3nfw22+/rfFBBx0EANh66621zc57tj9H+X6xRZjVuW4CR7xEREQe8cRLRETkUd7mlST9cN9992lbVCHVYYcdpm1230ebkpOL93aOpKQ5gPwrcEiFLW445JBDNJYCM8sWRRx88MEay+LoN910U+RrSOreLhGay2zRTbzF2vfbbz+NZdlBm/r88ccfKzzGpqfnz5+vsf08SzGgvTRTaOQ4jR8/Xtt69uypcbz55bVq1QIAXHbZZdpmiwlr166tcdTvg6SyAWDIkCEAwnN7582bp3G3bt0AAB9++GGlfco1hx56qMZRxU/296N+/foAgG233VbbevTooXHz5s017tu3b1r7maq4I17n3FDn3Arn3Oemra5zbrxzbl7Zv9tltptERET5IZFU8zAAnTdqGwRgQhAErQBMKPs/ERERxRE31RwEwUTnXIuNmrsCOKwsHg7gHQAD09ivtLFVmrYKVlI969at0zY7x2vChAkay9J8nPcYm6ThTj/9dG2LSqfZZe9kib2NSRotVqpZlvl85ZVXtM0u8ZlrbHVlu3btNJZ5irbS+YILLtBYLofYdOPzzz+vsaTqYu1lbON///vfAIBHH31U22xauhAup8hn2C4zG7X3s2WXhn3ggQcAhOfrx2KXj41qk926XnzxRW076aSTNP70008BhJe8zYef0U8//VTp7XaGiKzLYJfqzZUd3pItrmoQBMEyACj7t36sOzrn+jnnSp1zpd99912SL0eJ4vH2j8fcLx5vv3i80y/jxVVBEJQAKAGA4uLixJYk8kAKKewC83a0YUdQ8eaWZROfx9sWNz3yyCMA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7AlR9vnxxx81fvHFFyvc/t133/nsTtI44iUiIvKIJ14iIiKPCirV/Pzzz2s8bNiwCrdvs802Gj/++OMad+zYMaP9KgRRlco2Fb18+XKNb731VgDA/Pnzte2+++7TeNttt81EF7PCqaeeqnGtWrUAAKeccoq22VS9VHAeffTR2vb1119rLJdGFi1apG077rijxnaHrUStW7cu8rVk2b6ioiJty4fq9O+//17jIUOGAACOO+44bWvatHxL8pUrVwIo/7kBwBZbbKHxyJEjNZ4xYwaA8tkVAHDEEUdofNRRRwEAdt5558jnKlT9+/fXWD7Xdn2Fyy+/3HufksERLxERkUd5P+K1F+OvuOIKjaMWyH/jjTc0bt++fWY7VgDsMf7pp58qva8dfcnjPvnkE21bvHixxlEjXjt6tn8B5xpbMCKrp/3tb3+LvG/jxo0BhIvQTjvtNI2loM3ObZRRGRDe6EMKuWLNk7zuuusAAO+//762HXLIIRrffffdAPJjlGtNnDhR4zvvvDP078bkvSe7+Ybd71tGt3bE++9//1tjyTAce+yxSb1WLrHrAYwfP77C7TbrYFeuyma5+w1FRESUg3jiJSIi8ihvU82S7rGpmKVLl1a430MPPaRxixYtMt6vQmJTvr/++muF222qc5999tFYUsxTp07VtnjzeHM5vWzZVK0tioqy2WabAQB22mknbbMp96233hoAsOWWW2qbzEkHwnOG5VgvWbJE2+zlAZln3aNHD23r2bOnxjvssEOlfc1VUZ87m9o86KCDNJbLWnPmzNE2u0SqrB0AlKdPV6xYoW0vvPCCxlJsOHPmzMjHy++LLfysU6dO3PeTi0aNGqXxqlWrKty+du1ajXPleyBuL51zQ51zK5xzn5u2us658c65eWX/blfZcxAREdEGifx5MAxA543aBgGYEARBKwATyv5PREREccRNNQdBMNE512Kj5q4ADiuLhwN4B8BAZJF58+YBACZPnhx5u1TG9urVS9tsSo5S169fP43/+OMPAOGK5HfffVfj3377TeN27doByJ20UaZIWljmNQPhKv2FCxcCAG688UZts0tvfv75hiTVs88+q232OFuS4rbpZ5u2btWqFYBwRa+kuvOZTRvLnF57iSRKshX2drcu8c0332gsP28A6NChA4Dy36t8dsIJJ1R6u91TXS6vZLtkv9kaBEGw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n38GAGy77baRtzds2BAAcOWVV2pbp06dNG7dunUGe0eUnR544AGNv/76a41vvfXW6uhO3rO78X3zTflCi++//z4AYPHixdrWs2dPjWvUqAEA2H777bXNuahVkxPDES8REZFHPPESERF5xFQzpUWtWrUAAE2aNNG2RYvKd8WSFM7555+vbXvttZfGn3zySaa7mHd+/PFHAOGU11ZbbaWxpMcyZeXKlRoXFRVl9LXyzR9//AEAuOaaa7Rtzpw51dWdvPTLL79o/PrrrwMATjvtNG37/fffK338VVddpXH9+vUBAL1799a2J598UuO5c+cCADbdNLFTKke8REREHvHES0RE5FHWp5p/++03jV955RWNJUXz559/attBBx2ksVSk7bffftpWp04djaW67Z///Ke2PfLIIxrb9N2vv/4KANh11121zaZGt9hii4TfT76S4/Xss89q23HHHafxDz/8AAD466+/tG3p0qWeepc/bCXmscceCwD47LPPtO2cc87RePLkyQCAunXrattZZ52l8eGHH67xZpttBgBo2tRusV1Rr169NH7uuec0lt/TDh06aJtUigLAJpvwb3xbMduiRQsAQM2aNbVt/vz5Gktqk+Kz3ylPPPGExvZ3IR75fNrnsqlo+a664YYbtO2YY47RuKqXdfjbQERE5FHWjnhllGn/8lu7dm2lj5k3b57GTz/9NABg3333rfCcALD11lsDKB8VAOHRdZRvv/1WY3thvW/fvpU+rpDss88+Gu+yyy4af/jhhxXua4urKDY799D+RT9jxgwA5aNVAHj44Yc1ltHnV199pW22uO3QQw/VuF69egCAYcOGaZsdjUlmafbs2doW9fty0kknacxRLvDdd99pvOeee2osP9PGjRt771Mm2e/gli1bAgiPBlOZ+wqEM5wrVqwAAOy4447aZr/jo9js5GuvvaaxZDM/+ugjbevatavGP/30E4Bw8ZQUlCaDvxlEREQe8cRLRETkUdammi+99FIA8dPLscg8OZs6SNXq1as1vv322zVmqrmcTXvaQoUonPuZGHsc7bxPYZfhtOnhqVOnAgin1FatWqVx27ZtNW7Xrh2A2HMb5bNvi7tsKlmKhS677LJK3kl2sKl7m/qU92aPoZ0LKnOkx40bF3n7xx9/DCBcVGYLqmRZVev777/XONnvuuomhZMAcMghh2gsad1W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\n",
      "text/plain": [
       "<Figure size 576x576 with 25 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "####################################\n",
    "### RELOAD & GENERATE SAMPLE IMAGES\n",
    "####################################\n",
    "\n",
    "\n",
    "n_examples = 25\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    saver.restore(sess, save_path='./gan-conv.ckpt')\n",
    "\n",
    "    batch_randsample = np.random.uniform(-1, 1, size=(n_examples, gen_input_size))\n",
    "    new_examples = sess.run('generator/generator_outputs:0',\n",
    "                            feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                       'dropout:0': 0.0,\n",
    "                                       'is_training:0': False})\n",
    "\n",
    "fig, axes = plt.subplots(nrows=5, ncols=5, figsize=(8, 8),\n",
    "                         sharey=True, sharex=True)\n",
    "\n",
    "for image, ax in zip(new_examples, axes.flatten()):\n",
    "    ax.imshow(image.reshape((dis_input_size // 28, dis_input_size // 28)), cmap='binary')\n",
    "\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
